/*********************************************************************************
 *      Copyright:  (C) 2019 Wu Yujun<540726307@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  comport_main.c
 *    Description:  This file is com port test program
 *                 
 *        Version:  1.0.0(2019年06月06日)
 *         Author:  Wu Yujun <540726307@qq.com>
 *      ChangeLog:  1, Release initial version on "2019年06月06日 18时39分58秒"
 *                 
 ********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <libgen.h>
#include <signal.h>
#include "comport.h"
#include <time.h>


int     g_stop = 0 ;

void sighandler(int sig_num)
{   
    if(sig_num == SIGINT)
    {
        g_stop =1 ;
    }
    
}


void print_usage(const char *program_name)
{
    printf("\tUsage: %s [-d DELAY] [-t TIMEOUT] [-s SPEED] TTY\n",program_name) ;
    printf("\t-n      device TTY name you want to open\n\n") ;
    printf("\t-b      Set serial BaudRate\n") ;
    printf("\t-d      Set serial DataBit\n") ;
    printf("\t-p      Set serial Parity\n") ;
    printf("\t-s      Set serial StopBit\n") ;
    printf("\t-f      Set serial Flowctrl\n") ;

    printf("\t-t      Set TIMEOUT read from serial\n") ;
    printf("\tCtrl+c to exit %s...\n",program_name) ;

}

int main(int argc, char **argv)
{
    int                 opt = -1 ;
    char                *name = NULL ;
    long                baudrate = 115200 ;
    int                 databit = 8 ;
    char                parity = 'N' ;
    int                 stopbit = 1 ;
    char                flowctl = 'N' ;
    int                 timeout = 0 ;
    char                *program_name ;
    st_comport          *comport ;
    int                 fd_com = -1 ;
    fd_set              rset ;
    time_t              ticks ; 
    int                 rv = -1 ;
    char                rbuf[BUF_LEN] ;

    program_name = basename(argv[0]) ;

    const char *short_opts = "b:d:p:s:f:n:h";                    
    const struct option long_opts[] =   {  
        {"help", no_argument, NULL, 'h'},    
        {"baudrate", required_argument, NULL, 'b'},
        {"data", required_argument, NULL, 'd'},    
        {"parity", required_argument, NULL, 'p'},    
        {"stop", required_argument, NULL, 's'},    
        {"flowctl", required_argument, NULL, 'f'},    
        {"timeout", required_argument, NULL, 't'},
        {"name", required_argument, NULL, 'n'},

        {0, 0, 0, 0} 
    }; 
    while ((opt= getopt_long(argc, argv, short_opts, long_opts,NULL)) != -1) 
    {
        switch (opt) 
        {
            case 'b':
                baudrate = atoi(optarg) ;
                break ;
            case 'd':
                databit = atoi(optarg) ;
                break ;
            case 's':
                stopbit = atoi(optarg) ;
                break ;
            case 'p':
                parity = optarg[0] ;
                break ;
            case 'f':
                flowctl = optarg[0] ;
                break ;
            case 't':
                timeout = atoi(optarg) ;
                break ;
            case 'n':
                name = optarg ;
                break ;
            case 'h':
                print_usage(program_name) ;
                return 0 ;
        }
    }

    if(name == NULL)
    {
        printf("Please input TTY name , For example: \"%s -n /dev/ttyUSB0\"\n", program_name) ;
        print_usage(program_name) ;
        return -1 ;
    }

    comport = comport_init(name, baudrate,databit,parity,stopbit,flowctl) ;
    if(comport < 0)
    {
        printf("comport_init() failed\n") ;
        return -2 ;
    }
    fd_com = open_comport(comport) ;
    if(fd_com < 0)
    {
        printf("Open_comport() Failed\n") ;
        return -3 ;
    }

    signal(SIGINT, sighandler) ;
    fflush(stdin); //刷新标准输入缓冲区,把输入缓冲区里的东西丢弃
    printf("\nNow you can communicate with com port.....\n") ;
    while(!g_stop)
    {
        FD_ZERO(&rset) ;
        FD_SET(STDIN_FILENO, &rset) ;
        FD_SET(fd_com, &rset) ;
        rv = select(fd_com+1, &rset, NULL, NULL, NULL) ;
        if(rv < 0)
        {
            printf("select() failed: %s\n", strerror(errno)) ;
            goto cleanup ;
        }
        if(rv == 0)
        {
            printf("select() time out!\n") ;
            goto cleanup ;
        }
        ticks = time(NULL) ;

        /* 标准输入的发送到串口 */
        if( FD_ISSET(STDIN_FILENO, &rset) )
        {
            memset(rbuf, 0, sizeof(rbuf)) ;
            fgets(rbuf, sizeof(rbuf), stdin) ;
            if( write_comport(comport, rbuf, strlen(rbuf)) < 0)
            {
                printf("write to other side failure :%s\n", strerror(errno)) ;
                break ;
            }
            fflush(stdin); //刷新标准输入缓冲区,把输入缓冲区里的东西丢弃
        }

        /*串口发回来的打印到标准输出 */
        if( FD_ISSET(fd_com, &rset) )
        {
            memset(rbuf, 0, sizeof(rbuf)) ;
            rv = read_comport(comport, rbuf, BUF_LEN,timeout) ;
            if(rv <= 0)
            {
                printf("read() error: %s\n", strerror(errno)) ;
                break ;
            }
            printf("%.24s\n",ctime(&ticks)) ;
            printf("Read from serial:%s", rbuf) ;
        }

    }
    printf("Program %s exit!\n", program_name) ;


cleanup:
    comport_term(comport) ;

    /*       End Of Main      */
    return 0 ;
}

